/**
 * DatabaseManager.java
 *
 * @version 1.0
 * @author nicky.han
 */
package cn.etgps.etgps.manager;

import android.content.Context;

import com.j256.ormlite.android.apptools.OpenHelperManager;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.Where;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import cn.etgps.etgps.dataEntity.DataBaseEntity;
import cn.etgps.etgps.dataEntity.Model;
import cn.etgps.etgps.dataEntity.TruckBean;

/**
 * Manage the database.
 *
 * @author nicky.han
 */
public class DatabaseManager {
    /**
     * ORMLite's object. Used to manage table
     */
    private HashMap<String, Dao<Model, Integer>> mDataDaos = null;
    /**
     * ORMLite's object. Used to get Dao
     */
    private DataHelper mDataHelper = null;

    /**
     * Constructor method
     */
    public DatabaseManager(Context context) {
        mDataHelper = OpenHelperManager.getHelper(context, DataHelper.class);
        try {
            List<Class<? extends Model>> classes = new ArrayList<Class<? extends Model>>();
            classes.add(TruckBean.class);
            mDataDaos = mDataHelper.getDataDaos(classes);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * If no used the DataHelper, Must close it(ex.When Activity onDestory).
     */
    public void closeManager() {
        if (mDataHelper != null) {
            OpenHelperManager.releaseHelper();
            mDataHelper = null;
        }
    }

    /**
     * Add data to database
     */
    public boolean addModel(Model model) {
        try {
            int result = mDataDaos.get(model.getClass().getName()).create(model);
            if (result == 1) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Add data to database
     */
    public void addModels(List<? extends Model> models) {
        try {
            for (int i = 0; i < models.size(); i++) {
                addModel(models.get(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Delete data
     */
    public boolean deleteModel(Model model) {
        try {
            int result = mDataDaos.get(model.getClass().getName()).delete(model);
            if (result == 1) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Have no this data, create it. if exist, update this data
     */
    public boolean createOrUpdateModel(String className, Model model) {
        try {
            deleteModelById(className, model.getId());
            addModel(model);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * clear all data in table
     */
    public boolean clearTable(String className) {
        try {
            mDataDaos.get(className).delete(queryForAll(className));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Have no this data, create it. if exist, update this data
     */
    public boolean createOrUpdateModels(String className, List<Model> models) {
        try {
            for (int i = 0; i < models.size(); i++) {
                createOrUpdateModel(className, models.get(i));
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }


    /**
     * Delete data by id
     *
     * @param className used to find the current Dao
     */
    public boolean deleteModelById(String className, int id) {
        try {
            QueryBuilder<Model, Integer> qb = mDataDaos.get(className).queryBuilder();
            qb.where().eq(DataBaseEntity.ID, id);
            List<Model> model = qb.query();
            if (model != null && model.size() > 0) {
                int result = mDataDaos.get(model.get(0).getClass().getName()).delete(model.get(0));
                if (result != 1) {
                    return false;
                }
            }
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Get data object by id
     *
     * @param className used to find the current Dao
     */
    public Model getModelById(String className, int id) {
        try {
            QueryBuilder<Model, Integer> qb = mDataDaos.get(className).queryBuilder();
            qb.where().eq(DataBaseEntity.ID, id);
            List<Model> model = qb.query();
            if (model != null) {
                return model.get(0);
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Query all data in the table
     *
     * @param className used to find the current Dao
     */
    public List<Model> queryForAll(String className) {
        try {
            return mDataDaos.get(className).queryForAll();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Query data by current value
     *
     * @param className used to find the current Dao
     */
    public List<Model> queryByContentValue(String className, String columnName, String value, String orderByColumn,
            boolean ascending) {
        try {
            QueryBuilder<Model, Integer> qb = mDataDaos.get(className).queryBuilder();
            qb.where().like(columnName, "%" + value + "%");
            if (!"".equals(orderByColumn)) {
                qb.orderBy(orderByColumn, ascending);
            }
            return qb.query();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public QueryBuilder<Model, Integer> getQueryBuilder(String className) {
        return mDataDaos.get(className).queryBuilder();
    }

    /**
     * Query data by current value
     *
     * @param className used to find the current Dao
     */
    public List<Model> queryByContentValues(String className, List<String> columnNames, List<String> values,
            String orderByColumn, boolean ascending) {
        try {
            QueryBuilder<Model, Integer> qb = mDataDaos.get(className).queryBuilder();
            Where where = qb.where();
            for (int i = 0; i < columnNames.size(); i++) {
                if (i > 0) {
                    where.and();
                }
                where.eq(columnNames.get(i), columnNames.get(i));
            }
            if (!"".equals(orderByColumn)) {
                qb.orderBy(orderByColumn, ascending);
            }
            return qb.query();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public List<Model> getModelsByCount(String className, long from, long to, String orderByColumn, boolean ascending) {
        QueryBuilder<Model, Integer> qb = mDataDaos.get(className).queryBuilder();
        try {
            qb.offset(from);
            qb.limit((to - from));
            if (!"".equals(orderByColumn)) {
                qb.orderBy(orderByColumn, ascending);
            }
            List<Model> models = qb.query();
            return models;
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
        return null;
    }

    public List<Model> getModelsByCountAndValue(String className, long from, long to, String columnName, String value,
            String orderbyColumn, boolean ascending) {
        try {
            QueryBuilder<Model, Integer> qb = mDataDaos.get(className).queryBuilder();
            qb.where().eq(columnName, value);
            qb.offset(from);
            qb.limit((to - from));
            if (!"".equals(orderbyColumn)) {
                qb.orderBy(orderbyColumn, ascending);
            }
            List<Model> models = qb.query();
            return models;
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
        return null;
    }

}
